<template>
  <div id="app">
    <!-- <header-nav></header-nav> -->
    <transition name="fade" mode="out-in">
      <router-view class="view"></router-view>
    </transition>
    <div v-if="isShowNewInvitationDialog" class="dialogBigBoxapp">
      <div class="dialogBoxapp">
        <div class="dialogTitleapp">
          呼入请求
          <i
            @click="handleRejectCall"
            class="el-icon-close"
            style="position: absolute; right: 1rem; cursor: pointer"
          ></i>
        </div>
        <div style="margin-top: 15%">
          <span style="font-size: 2rem">{{
            this.getNewInvitationDialogContent()
          }}</span>
        </div>
        <div style="display: flex; justify-content: center; margin-top: 15%">
          <div style="text-align: right" @click="handleAccept">
            <img
              style="width: 5rem; cursor: pointer; margin-right: 8rem"
              src="@assets/images/call/tonghua.png"
            />
          </div>
          <div style="text-align: right" @click="handleRejectCall">
            <img
              style="width: 5rem; cursor: pointer"
              src="@assets/images/call/guaduan.png"
            />
          </div>
        </div>
      </div>
    </div>
    <!-- 
    <el-dialog
      title="通话请求"
      :visible.sync="isShowNewInvitationDialog"
      width="400px"
    >
      <span>{{ this.getNewInvitationDialogContent() }}</span>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handleRejectCall">拒绝</el-button>
        <el-button type="primary" @click="handleAccept">接听</el-button>
      </span>
    </el-dialog> -->

    <callRoom v-if="isLogin" ref="callRoom" />
    <CozeChat v-if="isLogin" ref="CozeChat" />
    <messageVoice v-if="isLogin" ref="messageVoice" />
    <!-- <Login v-show="false" ref="Login"></Login> -->
    <answerService
      v-if="showAnswerService"
      ref="answerService"
      :inviterName="inviterName"
    />
    
  </div>
</template>
<!-- <script src="../../public/debug/log4javascript.js"></script>  -->
<script>
import { mapState, mapMutations } from "vuex";
import { log } from "./utils";
import { getUsernameByUserid } from "./service";
//import HeaderNav from "./components/header-nav";
import { getActives, getNewtoken, getTrtcLogin } from "../src/api/index";
import answerService from "@/components/answer-service/index";
import callRoom from "@/components/call-room/index";
import CozeChat from "@/components/coze-chat/index";
import messageVoice from "@/components/message-voice/index";
import mp3 from "@assets/music/voice.mp3";
const Base64 = require("js-base64").Base64;
let timeout;

export default {
  name: "App",
  components: {
    answerService,
    callRoom,
    messageVoice,
    CozeChat
  },
  watch: {
    isLogin: function (newIsLogin, oldIsLogin) {
      if (newIsLogin !== oldIsLogin) {
        if (newIsLogin) {
          if (this.$router.history.current.path === "/login") {
            // 防止已在 '/' 路由下再次 push
            this.$router.push("/");
          }
        } else {
          this.$router.push("/login");
          window.location.reload();
          //退出房间
          //this.$refs.callRoom.leaveRoom();
        }
      }
    },
    // callStatus: function (newStatus, oldStatus) {
    //   console.log("新状态", newStatus, "旧状态", oldStatus);
    //   if (newStatus === "connected") {
    //     //退出房间
    //     this.$refs.callRoom.leaveRoom();
    //   }
    //   if (newStatus === "idle") {
    //     this.$refs.callRoom.createTrtc();
    //   }
    // },
    audioprofile: function (newStatus, oldStatus) {
      console.log("语音质量新状态", newStatus, "语音质量旧状态", oldStatus);
      //this.$refs.callRoom.createTrtc();
    },
  },
  computed: mapState({
    audioprofile: (state) => state.audioprofile, //语音质量
    isLogin: (state) => state.isLogin,
    loginUserInfo: (state) => state.loginUserInfo,
    userInfoDetails: (state) => state.userInfoDetails,
    callStatus: (state) => state.callStatus,
    isAccepted: (state) => state.isAccepted,
    meetingUserIdList: (state) => state.meetingUserIdList,
    muteVideoUserIdList: (state) => state.muteVideoUserIdList,
    muteAudioUserIdList: (state) => state.muteAudioUserIdList,
    showAnswerService: (state) => state.showAnswerService,
  }),
  async created() {
    console.log("更新日期：2023-02-10 15：00");
    this.initListener();
    await this.handleAutoLogin();
    //设置页面自适应
    (function (win, doc) {
      var fres = function () {
        var html = doc.documentElement;
        var w = html.clientWidth;
        w && (html.style.fontSize = w / 100 + "px"); //显示器31.9467 本机44.7467// fontsize设置成1/100大
      };
      if (document.readyState === "complete") {
        fres();
      } else {
        document.addEventListener("DOMContentLoaded", fres, false);
      }
      window.addEventListener("resize", fres, false); //监听页面缩放
    })(window, document); //自适应 √

    //日期格式
    Date.prototype.Format = function (fmt) {
      //author: meizz
      var o = {
        "M+": this.getMonth() + 1, //月份
        "d+": this.getDate(), //日
        "h+": this.getHours(), //小时
        "m+": this.getMinutes(), //分
        "s+": this.getSeconds(), //秒
        "q+": Math.floor((this.getMonth() + 3) / 3), //季度
        S: this.getMilliseconds(), //毫秒
      };
      if (/(y+)/.test(fmt))
        fmt = fmt.replace(
          RegExp.$1,
          (this.getFullYear() + "").substr(4 - RegExp.$1.length)
        );
      for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt))
          fmt = fmt.replace(
            RegExp.$1,
            RegExp.$1.length == 1
              ? o[k]
              : ("00" + o[k]).substr(("" + o[k]).length)
          );
      return fmt;
    };
  },
  mounted() {
    let that = this;
    this.heartTimer = setInterval(function () {
      that.getActive();
    }, 25 * 1000);
  },
  data() {
    return {
      appIsAccept: false, //是否接听电话
      appTwoMinutes: null, //呼叫两分钟计时器
      appAnswerMusic: null, //对方呼叫时候的响铃
      //showAnswerService:false,
      heartTimer: null,
      isInviterCanceled: false,
      isShowNewInvitationDialog: false,
      inviterName: "",
      callTypeDisplayName: "",
      inviteData: {},
      inviteID: "",
    };
  },

  destroyed() {
    this.removeListener();
    clearInterval(this.heartTimer);
    this.heartTimer = null;
  },
  methods: {
    ...mapMutations([
      "setshowAnswerService", //设置通讯类型
    ]),

    //播放音频
    appPlayAudio() {
      this.appAnswerMusic = null;
      this.appAnswerMusic = new Audio();
      this.appAnswerMusic.src = mp3;
      this.appAnswerMusic.loop = "loop";
      this.appAnswerMusic.play();
    },
    //停止音频
    appStopAudio() {
      console.log("停止音频", this.appAnswerMusic);
      if (this.appAnswerMusic != null) {
        this.appAnswerMusic.pause();
      }
    },
    async refreshToken() {
      let phoneNumber = localStorage.getItem("phoneNumber");
      let password = Base64.decode(localStorage.getItem("password"));
      let params = {
        tyid: phoneNumber,
        password: password,
      };
      await getNewtoken(params).then((res) => {
        console.log("获取token信息", res.token);
        console.log("获取过期时间", res.expiration);
        //存储token
        window.localStorage["token"] = JSON.stringify(res.token);
        //存储token过期时间
        window.localStorage["expiration"] = JSON.stringify(res.expiration);
        console.log('重新获取到的token: ' + JSON.stringify(res.token))
        this.$store.commit("setChatLog", {
            time: new Date().Format("yyyy-MM-dd hh:mm:ss"),
            content: "重新获取到的token:"+JSON.stringify(res.token)+';token过期时间:'+JSON.stringify(res.expiration),
          });
      }).catch((err)=>{
        console.log('刷新token失败',err)
        this.$store.commit("setChatLog", {
            time: new Date().Format("yyyy-MM-dd hh:mm:ss"),
            content: '刷新token失败:'+err,
          });
      })
    },
    //登录TRTC
    async loginTrtc() {
      const params = {
        acount: "admin_nikoyose_3033654362",
        paswd: "admin_nikoyose_3033654362",
        appid: 1400552732,
      };
      await getTrtcLogin(params).then((res) => {
        if (res.data.code == 0) {
          //存储token
          window.localStorage["trtctoken"] = JSON.stringify(res.data.token);
          //存储token过期时间
          window.localStorage["trtcexpiration"] = JSON.stringify(
            res.data.expiration
          );
        } else {
          this.$message.error(res.error_msg);
        }
      });
    },
    //调用心跳接口      
    getActive: async function () {    
      if (this.$route.path != "/login") {
        console.log(this.$refs.callRoom)
        //当前时间   
        let currentTime = new Date().getTime();
        //token过期时间-30s   心跳接口25s调用一次，为了token更新及时，这里用过期时间-30s判断
        let expirationTime =
          new Date(JSON.parse(localStorage.expiration)).getTime() - 30000;
        //token已经过期
        if (currentTime > expirationTime) {
          this.refreshToken(); //重新获取token
          console.log('token过期，重新获取token')
          this.$store.commit("setChatLog", {
            time: new Date().Format("yyyy-MM-dd hh:mm:ss"),
            content: "token过期，重新获取",
          });
        }
        let phone = this.userInfoDetails.account.tel;
        await getActives(phone)
          .then(
            //console.log("调用心跳接口成功")
            () => {
              // this.$refs.callRoom.log.info("调用心跳接口成功"); //activeLog();//将心跳记录进日志中
              this.$refs.callRoom.logList +=
                new Date().Format("yyyy-MM-dd hh:mm:ss") +
                "  info - 调用心跳接口成功\n";
            }
          )
          .catch(() => {
            console.log("调用心跳接口失败")
            // this.$refs.callRoom.log.error("调用心跳接口失败"); //activeLog();//将心跳记录进日志中
            this.$refs.callRoom.logList +=
              new Date().Format("yyyy-MM-dd hh:mm:ss") +
              "  error - 调用心跳接口失败\n";
          });

        let newdate = new Date().getTime();
        let trtcdate = new Date(JSON.parse(localStorage.trtcexpiration)).getTime() - 30000
        //如果当前时间大于trtctoken失效时间，那么重新获取token
        if (newdate >= trtcdate) {
          console.log("****************重新获取trtctoken****************");
          this.loginTrtc(); //重新获取trtc的token
        }
      }
    },
    handleAutoLogin: async function () {},
    initListener: function () {
      this.$trtcCalling.on(this.TrtcCalling.EVENT.ERROR, this.handleError);
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.INVITED,
        this.handleNewInvitationReceived
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.USER_ACCEPT,
        this.handleUserAccept
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.USER_ENTER,
        this.handleUserEnter
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.USER_LEAVE,
        this.handleUserLeave
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.REJECT,
        this.handleInviteeReject
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.LINE_BUSY,
        this.handleInviteeLineBusy
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.CALLING_CANCEL,
        this.handleInviterCancel
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.KICKED_OUT,
        this.handleKickedOut
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.CALLING_TIMEOUT,
        this.handleCallTimeout
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.NO_RESP,
        this.handleNoResponse
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.CALLING_END,
        this.handleCallEnd
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.USER_VIDEO_AVAILABLE,
        this.handleUserVideoChange
      );
      this.$trtcCalling.on(
        this.TrtcCalling.EVENT.USER_AUDIO_AVAILABLE,
        this.handleUserAudioChange
      );
    },
    removeListener: function () {
      this.$trtcCalling.off(this.TrtcCalling.EVENT.ERROR, this.handleError);
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.INVITED,
        this.handleNewInvitationReceived
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.USER_ACCEPT,
        this.handleUserAccept
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.USER_ENTER,
        this.handleUserEnter
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.USER_LEAVE,
        this.handleUserLeave
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.REJECT,
        this.handleInviteeReject
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.LINE_BUSY,
        this.handleInviteeLineBusy
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.CALLING_CANCEL,
        this.handleInviterCancel
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.KICKED_OUT,
        this.handleKickedOut
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.CALLING_TIMEOUT,
        this.handleCallTimeout
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.NO_RESP,
        this.handleNoResponse
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.CALLING_END,
        this.handleCallEnd
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.USER_VIDEO_AVAILABLE,
        this.handleUserVideoChange
      );
      this.$trtcCalling.off(
        this.TrtcCalling.EVENT.USER_AUDIO_AVAILABLE,
        this.handleUserAudioChange
      );
    },
    handleError: function () {},
    handleNewInvitationReceived: async function (payload) {
      //如果正在对讲中，则不接收来电提示
      if (
        this.$refs.callRoom.showCallDialog == true ||
        this.callStatus == "calling" ||
        this.callStatus == "connected"
      ) {
        return;
      }
      const { inviteID, sponsor, inviteData } = payload;
      log(`handleNewInvitationReceived ${JSON.stringify(payload)}`);
      if (inviteData.callEnd) {
        // 最后一个人发送 invite 进行挂断
        this.$store.commit("updateCallStatus", "idle");
        return;
      }
      // if (sponsor === this.loginUserInfo.userId) {
      //   // 邀请人是自己, 同一个账号有可能在多端登录
      //   return;
      // }
      // 这里需要考虑忙线的情况
      if (this.callStatus === "calling" || this.callStatus === "connected") {
        await this.$trtcCalling.reject({ inviteID, isBusy: true });
        return;
      }
      //const { callType } = inviteData;
      this.inviteData = inviteData;
      this.inviteID = inviteID;
      this.isInviterCanceled = false;
      this.$store.commit("updateIsInviter", false);
      this.$store.commit("updateCallStatus", "calling");
      const userName = sponsor;
      this.inviterName = userName;
      // this.callTypeDisplayName =
      //   callType === this.TrtcCalling.CALL_TYPE.AUDIO_CALL
      //     ? "语音通话"
      //     : "视频通话";
      this.isShowNewInvitationDialog = true;
      this.appPlayAudio(); //响铃
      this.appIsAccept = false; //代表还未接听
      if (this.appTwoMinutes != null) {
        clearTimeout(this.appTwoMinutes); //清空两分钟计时器
        this.appTwoMinutes = null;
      }
      this.appTwoMinutes = setTimeout(() => {
        //两分钟未接听,则关闭弹窗
        if (this.appIsAccept == false) {
          this.handleRejectCall();
        }
      }, 2 * 60 * 1000);
    },
    getNewInvitationDialogContent: function () {
      //return `来自${this.inviterName}的${this.callTypeDisplayName}`;
      return `来自${this.inviterName}的呼入请求`;
    },
    handleRejectCall: async function () {
      try {
        const { callType } = this.inviteData;
        await this.$trtcCalling.reject({
          inviteID: this.inviteID,
          isBusy: false,
          callType,
        });
        this.dissolveMeetingIfNeed();
      } catch (e) {
        this.dissolveMeetingIfNeed();
      }
      clearTimeout(this.appTwoMinutes); //清空两分钟计时器
      this.appTwoMinutes = null;
    },

    handleAccept: function () {
      this.handleDebounce(this.handleAcceptCall(), 500);
    },

    handleDebounce: function (func, wait) {
      let context = this;
      let args = arguments;
      if (timeout) clearTimeout(timeout);
      timeout = setTimeout(() => {
        func.apply(context, args);
      }, wait);
    },

    //接听电话
    handleAcceptCall: async function () {
      // alert('当前通话状态',this.callStatus)
      // if(this.callStatus === "calling"|| this.callStatus === "connected"){
      //   console.log('正在通话中，不弹出弹窗')
      //   return
      // }
      try {
        const { callType, roomID } = this.inviteData;
        this.$store.commit("userJoinMeeting", this.loginUserInfo.userId);
        await this.$trtcCalling.accept({
          inviteID: this.inviteID,
          roomID,
          callType, //通话类型1：语音
        });
        this.isShowNewInvitationDialog = false;
        this.appStopAudio(); //铃声停止
        this.appIsAccept = true; //标志着已接听
        clearTimeout(this.appTwoMinutes); //清空两分钟计时器
        this.appTwoMinutes = null;
        if (
          callType === this.TrtcCalling.CALL_TYPE.AUDIO_CALL &&
          this.$router.history.current.fullPath !== "/audio-call"
        ) {
          this.setshowAnswerService(true);
          //this.$refs.answerService.queryTime();//打开通话计时器
          //this.$router.push("/audio-call");
        } else if (
          callType === this.TrtcCalling.CALL_TYPE.VIDEO_CALL &&
          this.$router.history.current.fullPath !== "/video-call"
        ) {
          this.$router.push("/video-call");
        }
      } catch (e) {
        console.log("******************接电话失败***********************");
        this.dissolveMeetingIfNeed();
      }
    },
    handleUserAccept: function ({ userID }) {
      this.$store.commit("userAccepted", true);
      console.log(userID, "accepted");
    },
    handleUserEnter: function ({ userID }) {
      // 建立连接
      this.$store.commit("userJoinMeeting", userID);
      if (this.callStatus === "calling") {
        // 如果是邀请者, 则建立连接
        this.$nextTick(() => {
          // 需要先等远程用户 id 的节点渲染到 dom 上
          this.$store.commit("updateCallStatus", "connected");
        });
      } else {
        // 第n (n >= 3)个人被邀请入会, 并且他不是第 n 个人的邀请人
        this.$nextTick(() => {
          // 需要先等远程用户 id 的节点渲染到 dom 上
          this.$trtcCalling.startRemoteView({
            userID: userID,
            videoViewDomID: `video-${userID}`,
          });
        });
      }
    },
    handleUserLeave: function ({ userID }) {
      if (this.meetingUserIdList.length == 2) {
        this.$store.commit("updateCallStatus", "idle");
      }
      this.$store.commit("userLeaveMeeting", userID);
    },
    handleInviteeReject: async function ({ userID }) {
      const userName = await getUsernameByUserid(userID);
      this.$message.warning(`${userName}拒绝通话`);
      this.$router.push("/");
      this.dissolveMeetingIfNeed();
    },
    handleInviteeLineBusy: async function ({ userID }) {
      const userName = await getUsernameByUserid(userID);
      this.$message.warning(`${userName}忙线`);
      this.$router.push("/");
      this.dissolveMeetingIfNeed();
    },
    handleInviterCancel: function () {
      this.isShowNewInvitationDialog = false;
      this.appStopAudio(); //铃声停止
      this.$message.warning("通话已取消");
      this.dissolveMeetingIfNeed();
    },
    handleKickedOut: function () {
      //重复登陆，被踢出房间
      this.$store.commit("userAccepted", false);
      this.$trtcCalling.logout();
      this.$store.commit("userLogoutSuccess");
    },
    // 作为被邀请方会收到，收到该回调说明本次通话超时未应答
    handleCallTimeout: function () {
      this.isShowNewInvitationDialog = false;
      this.appStopAudio(); //铃声停止
      this.$message.warning("通话超时未应答");
      this.dissolveMeetingIfNeed();
    },
    //通话结束
    handleCallEnd: function () {
      this.$message.success("通话已结束");
      this.$trtcCalling.hangup();
      this.dissolveMeetingIfNeed();
      this.setshowAnswerService(false);
      //this.$router.push("/search-user");
      this.$store.commit("userAccepted", false);
    },
    handleNoResponse: async function ({ userID }) {
      const userName = await getUsernameByUserid(userID);
      this.$message.warning(`${userName}无应答`);
      //this.$router.push("/search-user");
      this.setshowAnswerService(false);
      this.dissolveMeetingIfNeed();
    },
    handleUserVideoChange: function ({ userID, isVideoAvailable }) {
      log(
        `handleUserVideoChange userID, ${userID} isVideoAvailable ${isVideoAvailable}`
      );
      if (isVideoAvailable) {
        const muteUserList = this.muteAudioUserIdList.filter(
          (currentID) => currentID !== userID
        );
        this.$store.commit("updateMuteVideoUserIdList", muteUserList);
      } else {
        const muteUserList = this.muteAudioUserIdList.concat(userID);
        this.$store.commit("updateMuteVideoUserIdList", muteUserList);
      }
    },
    handleUserAudioChange: function ({ userID, isAudioAvailable }) {
      log(
        `handleUserAudioChange userID, ${userID} isAudioAvailable ${isAudioAvailable}`
      );
      if (isAudioAvailable) {
        const muteUserList = this.muteAudioUserIdList.filter(
          (currentID) => currentID !== userID
        );
        this.$store.commit("updateMuteAudioUserIdList", muteUserList);
      } else {
        const muteUserList = this.muteAudioUserIdList.concat(userID);
        this.$store.commit("updateMuteAudioUserIdList", muteUserList);
      }
    },
    dissolveMeetingIfNeed() {
      this.$store.commit("updateCallStatus", "idle");
      this.isShowNewInvitationDialog = false;
      this.appStopAudio(); //铃声停止
      if (this.meetingUserIdList.length < 2) {
        this.$store.commit("dissolveMeeting");
      }
    },
  },
};
</script>

<style>
html,
body {
  margin: 0;
  padding: 0px;
  height: 100%;
}
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin: 0;
  padding: 0;
  background: aliceblue;
  height: 100%;
}
.dialogBigBoxapp {
  z-index: 999;
  width: 100%;
  height: 100%;
  background-color: #0000006b;
  position: absolute;
  left: 0rem;
  top: 0rem;
}
.dialogBoxapp {
  width: 40rem;
  height: 50%;
  background-color: white;
  position: absolute;
  left: 30rem;
  top: 50%;
  transform: translateY(-50%);
  border-radius: 0.5rem;
  padding-bottom: 3rem;
}
.dialogTitleapp {
  padding: 0.6rem 1rem 0rem;
  text-align: left;
  font-size: 1.5rem;
}
@media screen and (max-width: 767px) {
  .el-message {
    min-width: 180px;
  }
}
</style>
